﻿using SManaModel.entities;
using SManaModel.models;

using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

namespace SManaApi.Services
{
    public class BaseService<TEntity> : IBaseService<TEntity> where TEntity : class
    {
        protected readonly MyDbContext _dbContext;

        public BaseService(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public virtual int GetCount(Expression<Func<TEntity, bool>>? whereExpression = default)
        {
            var count = whereExpression is not null ?
                _dbContext.Set<TEntity>()?.Where(whereExpression)?.Count()
                : _dbContext.Set<TEntity>().Count();
            return count ?? 0;
        }

        public virtual IQueryable<TEntity>? GetEntities()
        {
            var entities = _dbContext.Set<TEntity>().AsQueryable();
            return entities;
        }

        public virtual IQueryable<TEntity>? GetEntitiesByPage<TKey>(ServicePageComponent<TEntity, TKey> servicePageComponent)
        {
            if (servicePageComponent is null)
            {
                throw new ArgumentNullException(nameof(servicePageComponent));
            }

            if (servicePageComponent.OrderByExpression is null)
            {
                throw new ArgumentNullException(nameof(servicePageComponent.OrderByExpression));
            }

            IQueryable<TEntity>? entities = servicePageComponent.IsAscending ?
                _dbContext.Set<TEntity>().OrderBy<TEntity, TKey>(servicePageComponent.OrderByExpression) :
                _dbContext.Set<TEntity>().OrderByDescending<TEntity, TKey>(servicePageComponent.OrderByExpression);
            entities = entities.Skip(servicePageComponent.PageComponent.SkipSize).Take(servicePageComponent.PageComponent.PageSize);
            if (servicePageComponent.WhereExpression != null)
                entities = entities.Where(servicePageComponent.WhereExpression);
            return entities;
        }

        public virtual IQueryable<TEntity>? GetEntity(Expression<Func<TEntity, bool>> whereExpression)
        {
            if (whereExpression is null)
            {
                return null;
            }

            var entities = _dbContext.Set<TEntity>().Where(whereExpression);
            return entities;
        }

        public virtual int DeleteEntity(Expression<Func<TEntity, bool>>? whereExpression, DbContext? dbContext = default)
        {

            if (whereExpression is null)
            {
                return 0;
            }

            dbContext ??= _dbContext;
            var entity = GetEntity(whereExpression)?.FirstOrDefault();
            if (entity == null)
                return 0;

            dbContext.Set<TEntity>().Remove(entity);
            //_dbContext.Entry<Entity>(entity).State = Microsoft.EntityFrameworkCore.EntityState.Deleted;
            var n = _dbContext.SaveChanges();
            return n;

        }

        public virtual int AddEntity(TEntity? entity, DbContext? dbContext = default)
        {
            if (entity is null)
            {
                return 0;
            }

            dbContext ??= _dbContext;
            dbContext.Set<TEntity>().Add(entity);
            //_dbContext.Entry<Entity>(entity).State = Microsoft.EntityFrameworkCore.EntityState.Added;
            var n = _dbContext.SaveChanges();
            return n;
        }

        public virtual int UpdateEntity(TEntity? entity, DbContext? dbContext = default)
        {
            if (entity is null)
            {
                return 0;
            }


            dbContext ??= _dbContext;
            dbContext.Set<TEntity>().Update(entity);
            //_dbContext.Entry<Entity>(entity).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
            var n = _dbContext.SaveChanges();
            return n;
        }
    }


}
